package com.sc.nft.service.impl;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sc.nft.dao.UserEcologyPointsWalletDao;
import com.sc.nft.entity.*;
import com.sc.nft.entity.vo.AdminDaoEcologyPointWalletPageVO;
import com.sc.nft.entity.vo.AdminEcologyPointsUserWalletPageVO;
import com.sc.nft.entity.vo.AdminUserEcologyPointWalletPageVO;
import com.sc.nft.entity.vo.ecology.EcologyPointWalletExpendPageVO;
import com.sc.nft.entity.vo.ecology.EcologyPointWalletPageVO;
import com.sc.nft.enums.DaoEcologyPointsWalletLogTypeEnum;
import com.sc.nft.enums.EcologyIncomeTypeEnum;
import com.sc.nft.enums.EcologyPointsWalletEnum;
import com.sc.nft.enums.UserEcologyExpenditureTypeEnum;
import com.sc.nft.exception.GlobalRunTimeException;
import com.sc.nft.service.DaoEcologyPointsWalletService;
import com.sc.nft.service.UserEcologyPointsWalletLogService;
import com.sc.nft.service.UserEcologyPointsWalletService;
import com.sc.nft.util.BigDecimalUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Objects;

/**
 * <p>
 * 用户生态积分钱包 服务实现类
 * </p>
 *
 * @author liGen
 * @since 2024-11-26
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class UserEcologyPointsWalletServiceImpl implements UserEcologyPointsWalletService {
    private final UserEcologyPointsWalletDao userEcologyPointsWalletDao;
    private final UserEcologyPointsWalletLogService userEcologyPointsWalletLogService;
    private final DaoEcologyPointsWalletService daoEcologyPointsWalletService;

    @Override
    public UserEcologyPointsWallet getOneByUserIdAndPointId(Long pointsId, Long userId) {
        return userEcologyPointsWalletDao.getOneByUserIdAndPointId(pointsId,userId);
    }

    @Override
    public boolean adjustAmount(Long userId, Long pointId,String pointName, BigDecimal amount, EcologyPointsWalletEnum ecologyPointsWalletEnum, String remark) {
        UserEcologyPointsWallet ecologyPointsWallet = userEcologyPointsWalletDao.getOneByUserIdAndPointId(pointId,userId);
        if (Objects.isNull(ecologyPointsWallet)) {
            ecologyPointsWallet = saveWallet(userId, pointId,pointName,BigDecimal.ZERO,BigDecimal.ZERO,BigDecimal.ZERO);
            if (!ecologyPointsWalletEnum.getIsAdd()) {
                return Boolean.FALSE;
            }
        }
        Boolean walletFlag = Boolean.FALSE;
        Boolean walletLogFlag = Boolean.FALSE;
        if (ecologyPointsWalletEnum.getIsAdd()) {
            // 添加
            walletFlag = userEcologyPointsWalletDao.addAmount(ecologyPointsWallet.getId(), amount, ecologyPointsWallet.getAmount());
        } else {
            // 减少
            if (ecologyPointsWallet.getAmount().compareTo(amount) < 0) {
                return Boolean.FALSE;
            }
            walletFlag = userEcologyPointsWalletDao.subAmount(ecologyPointsWallet.getId(), amount, ecologyPointsWallet.getAmount());
        }
        UserEcologyPointsWalletLog userEcologyPointsWalletLog = new UserEcologyPointsWalletLog();
        userEcologyPointsWalletLog.setUserId(userId);
        userEcologyPointsWalletLog.setUserEcologyPointsWalletId(ecologyPointsWallet.getId());
        userEcologyPointsWalletLog.setType(ecologyPointsWalletEnum);
        userEcologyPointsWalletLog.setTypeName(ecologyPointsWalletEnum.getDescription());
        userEcologyPointsWalletLog.setAmount(amount);
        userEcologyPointsWalletLog.setBeforeBalance(ecologyPointsWallet.getAmount());
        if (ecologyPointsWalletEnum.getIsAdd()) {
            userEcologyPointsWalletLog.setAfterBalance(ecologyPointsWallet.getAmount().add(amount));
        }else {
            userEcologyPointsWalletLog.setAfterBalance(ecologyPointsWallet.getAmount().subtract(amount));
        }
        userEcologyPointsWalletLog.setIsAdd(ecologyPointsWalletEnum.getIsAdd());
        userEcologyPointsWalletLog.setRemark(remark);
        walletLogFlag = userEcologyPointsWalletLogService.save(userEcologyPointsWalletLog);
        return walletFlag && walletLogFlag;
    }

    private UserEcologyPointsWallet saveWallet(Long userId, Long pointId, String pointName,BigDecimal amount,BigDecimal sumExpendAmount,BigDecimal sumIncomeAmount) {
        UserEcologyPointsWallet userEcologyPointsWallet = new UserEcologyPointsWallet();
        userEcologyPointsWallet.setUserId(userId);
        userEcologyPointsWallet.setPointsId(pointId);
        userEcologyPointsWallet.setPointsName(pointName);
        userEcologyPointsWallet.setAmount(amount);
        userEcologyPointsWallet.setSumExpendAmount(sumExpendAmount);
        userEcologyPointsWallet.setSumIncomeAmount(sumIncomeAmount);
        userEcologyPointsWalletDao.save(userEcologyPointsWallet);
        return userEcologyPointsWallet;
    }

    /**
     * 用户积分列表根据daoid条件查询
     *
     * @param pageNo
     * @param pageSize
     * @param userCreatorId
     * @return
     */
    @Override
    public IPage<EcologyPointWalletPageVO> userPage(Integer pageNo, Integer pageSize, Long userCreatorId,Long userId) {
        return userEcologyPointsWalletDao.userPage(pageNo,pageSize,userCreatorId,userId);
    }

    /**
     * 用户钱包支出记录
     *
     * @param pageNo
     * @param pageSize
     * @param userPointsWalletId
     * @param userId
     * @return
     */
    @Override
    public IPage<EcologyPointWalletExpendPageVO> userEcologyPointsExpend(Integer pageNo, Integer pageSize, Long userPointsWalletId, Long userId) {
        if (userPointsWalletId == 0L) {
            return new Page<>();
        }
        IPage<EcologyPointWalletExpendPageVO> page = userEcologyPointsWalletDao.userEcologyPointsExpend(pageNo, pageSize, userPointsWalletId, userId);
        for (EcologyPointWalletExpendPageVO expendPageVO : page.getRecords()) {
            expendPageVO.setTypeName(expendPageVO.getType().getDescription());
            if (StrUtil.isBlank(expendPageVO.getRemark())) {
                expendPageVO.setRemark(expendPageVO.getTypeName());
            }
        }
        return page;
    }

    /**
     * 编辑用户生态燃料
     * @param id
     * @param ecologyPointsWalletEnum
     * @param amountString
     * @param remark
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void editUserPoints(Long id, Long userId,  String pointsName , EcologyPointsWalletEnum ecologyPointsWalletEnum,String amountString, String remark) {
        //要加的金额
        BigDecimal amount = Convert.toBigDecimal(amountString).setScale(2,BigDecimal.ROUND_DOWN);
        Assert.isTrue(NumberUtil.isGreater(amount,BigDecimal.ZERO),()-> new GlobalRunTimeException("金额不能小于0"));
            Assert.isTrue(adjustAmount(userId,id,pointsName,amount,ecologyPointsWalletEnum,remark),()-> new GlobalRunTimeException("操作失败"));
        //用户收支表
        if (ecologyPointsWalletEnum == EcologyPointsWalletEnum.SYSTEM_ADD) {
            UserEcologyExpenditureRecord userEcologyExpenditureRecord = new UserEcologyExpenditureRecord();
            userEcologyExpenditureRecord.setUserId(userId);
            userEcologyExpenditureRecord.setDateTime(Convert.toInt(DateUtil.format(DateTime.now(), "yyyyMMdd")));
            userEcologyExpenditureRecord.setType(UserEcologyExpenditureTypeEnum.ECOLOGY_MARK);
            userEcologyExpenditureRecord.setTypeName(UserEcologyExpenditureTypeEnum.ECOLOGY_MARK.getDescription());
            userEcologyExpenditureRecord.setRemark(EcologyPointsWalletEnum.SYSTEM_ADD.getDescription());
            userEcologyExpenditureRecord.setLinkId(id);
            userEcologyExpenditureRecord.setLinkName(UserEcologyExpenditureTypeEnum.ECOLOGY_MARK.getDescription());
            userEcologyExpenditureRecord.setLinkCount(BigDecimalUtils.p(amountString));
            userEcologyExpenditureRecord.setLinkImage(StrUtil.EMPTY);
            userEcologyExpenditureRecord.insert();
        }

    }
    @Override
    public Page<AdminEcologyPointsUserWalletPageVO> getUserPage(String userTel, Integer pageNo, Integer pageSize) {
        return userEcologyPointsWalletDao.getUserPage(userTel,pageNo,pageSize);
    }

    @Override
    public IPage<AdminUserEcologyPointWalletPageVO> adminUserPointWalletPage(Integer pageNo, Integer pageSize, Long userId){
        return userEcologyPointsWalletDao.adminUserPointWalletPage(pageNo,pageSize,userId);
    }


    @Override
    public IPage<AdminDaoEcologyPointWalletPageVO> adminDaoPointWalletPage(Integer pageNo, Integer pageSize, Long userCreatorId) {
        return userEcologyPointsWalletDao.adminDaoPointWalletPage(pageNo,pageSize,userCreatorId);
    }

    @Override
    public UserEcologyPointsWallet getOneByUserId(Long userId) {
        return userEcologyPointsWalletDao.getOneByUserId(userId);
    }
    @Override
    public Boolean addUserEcologyPointsWallet(Long userId, BigDecimal amount, EcologyPointsWalletEnum type, String remark) {
        UserEcologyPointsWallet ecologyPointsWallet = getOneByUserId(userId);
        Boolean flag = userEcologyPointsWalletDao.addEcologyPoints(userId, amount);
        //日志
        UserEcologyPointsWalletLog userEcologyPointsWalletLog = new UserEcologyPointsWalletLog();
        userEcologyPointsWalletLog.setUserId(userId);
        userEcologyPointsWalletLog.setType(type);
        userEcologyPointsWalletLog.setAmount(amount);
        userEcologyPointsWalletLog.setBeforeBalance(ecologyPointsWallet.getAmount());
        userEcologyPointsWalletLog.setAfterBalance(ecologyPointsWallet.getAmount().add(amount));
        userEcologyPointsWalletLog.setIsAdd(type.getIsAdd());
        userEcologyPointsWalletLog.setRemark(remark);
        userEcologyPointsWalletLogService.save(userEcologyPointsWalletLog);

        return flag;
    }

}
